// serviceclient
package serviceclient

import (
	//	"encoding/json"
	"errors"
	"io"
	"log"
	"strings"
	"swim/etc"
	"swim/redisclient"
	"swim/request"
	"sync"
	"time"

	//	"github.com/garyburd/redigo/redis"
)

type GroupInfo struct {
	Id        int    //组ID
	ParentId  int    //组的父ID
	Account   string //组的账号
	Levelid   string //层级ID
	Name      string //组名
	Phone     string //电话
	Address   string //地址
	FirstHint string //首次对话提示语
	Maxclient int    //最多添加的服务人员数量
}

//服务人员基本信息
type SUser struct {
	ID         int64
	Group      GroupInfo //所属群信息
	Name       string
	Levelid    string
	Account    string
	Pwd        string
	Phone      string
	Offer      string
	Last_login string
}

type ServiceClient struct {
	LoginId         string            //登录ID
	Ip              string            //登录的IP
	TermType        int               //终端类型0为PC浏览器
	TaskFlag        int               //0表示空闲，1表示有会话任务
	Status          int               //状态
	LoginTime       time.Time         //最近登录时间
	SesionTickCount time.Time         //最近会话时间
	CurGroup        *ServiceGroup     //服务人员所属群
	User            SUser             //所属服务用户信息
	TaskPool        chan string       //用于发消息的任务池
	Sessions        map[string]string //个人会话组key为最新接入任务sid,value是对方SID
	w               io.Writer
	rdLock          sync.RWMutex //同步读写锁
}
type ServiceSesion struct {
	Sid             string              //会话
	IP              string              //登录的IP
	CType           int                 //会话类型，0为web客户会话,1为客服人员会话
	SesionTickCount time.Time           //最后会话时间
	UserService     *ServiceClient      //所属服务用户信息
	MsgPool         chan request.WebMsg //消息缓存池
	wr              io.Writer
	rdLock          sync.RWMutex //同步读写锁
}

func (c *ServiceClient) Write(content string) {
	defer c.UpdateUserTime()
	io.WriteString(c.w, content)
}

//添加对话任务
//peer_sid为对方会话ID，sid是本客户端的会话ID，若本会话是web匿名服务端的那么，peer_id是匿名会话ID，返回当前会话服务端ID
//
func (c *ServiceClient) AddSession(peer_sid, sid string) string {
	c.rdLock.Lock()
	c.Sessions[peer_sid] = sid
	c.rdLock.Unlock()
	val := peer_sid + ":" + sid
	select {
	case c.TaskPool <- val:
		//do nothing
	default:
		//warnning!
	}
	/*
		key := c.User.Account + "_accountSession"
		val := peer_sid + ":" + sid
		conn := redisclient.G_redisPool.Get()
		_, err := conn.Do("LPUSH", key, val)
		if err != nil {
			log.Fatal(err.Error())
		}
		//	redisclient.G_redisPool.Get().Do("EXPIRE", key, etc.S_MSG_LIFE_CYCLE)
		if err != nil {
			log.Fatal(err.Error())
		}*/
	return sid
}

//返回第一个参数对方SID，第二个是本身SID
func (c *ServiceClient) GetSession() (string, string, int) {
	defer c.UpdateUserTime() //更新tick生存时间
	var sOne string
	select {
	case sOne = <-c.TaskPool:
		if strings.HasPrefix(sOne, "http://") {
			return "", sOne, 2
		}
		sArray := strings.Split(sOne, ":")
		//c.RemoveSession(sArray[0])
		if len(sArray) == 2 {
			return sArray[0], sArray[1], 1
		} else {
			log.Println("---- " + sOne)
			return "", "", 0
		}
	case <-time.After(time.Second * etc.S_QUERY_MSG_TIME):
		//log.Println("time out!!!")
		return "", "", 0
	}
	/*
		key := c.User.Account + "_accountSession"
		var sOne string
		sObj, sErr := redisclient.G_redisPool.Get().Do("BRPOP", key, etc.S_QUERY_MSG_TIME)
		//sObj, sErr := redisclient.G_redisPool.Get().Do("RPOP", key)
		if sErr != nil {
			log.Println(sErr.Error())
			return "", "", false
		} else {
			msgObj, bCommit := sObj.([]interface{})
			if bCommit {
				msgByte, bIsBytes := msgObj[1].([]byte)
				if bIsBytes {
					sOne = string(msgByte)
					sArray := strings.Split(sOne, ":")
					//c.RemoveSession(sArray[0])
					return sArray[0], sArray[1], true
				}
			}
		}
		return "", "", false
	*/
}

func (c *ServiceClient) RemoveSession(peer_sid string) bool {
	s := c.Sessions[peer_sid]
	if s == "" {
		return false
	}
	c.rdLock.Lock()
	delete(c.Sessions, peer_sid)
	c.rdLock.Unlock()
	return true
}

func (c *ServiceClient) RemoveServiceSession(service_sid string) {

	for peer_sid, sid := range c.Sessions {
		if sid == service_sid {
			c.rdLock.Lock()
			delete(c.Sessions, peer_sid)
			c.rdLock.Unlock()
		}
	}
	return
}

func (c *ServiceClient) isExpire() bool {
	c.rdLock.RLock()
	defer c.rdLock.RUnlock()
	return time.Now().Sub(c.SesionTickCount) > etc.S_LIFESPAN*time.Second
}

func (c *ServiceClient) AddCustomerUrl(strUrl string) {
	select {
	case c.TaskPool <- strUrl:
		//do nothing
	default:
		//warnning!
	}
}

func (c *ServiceClient) On_Logout() {
	//清除redis对应记录
	close(c.TaskPool)
	/*
		key := c.User.Account + "_accountSession"
		redisclient.G_redisPool.Get().Do("DEL", key)
	*/
}
func (c *ServiceClient) UpdateUserTime() {
	c.rdLock.Lock()
	c.SesionTickCount = time.Now()
	c.rdLock.Unlock()
}

func (s *ServiceSesion) Write(content string) {
	s.UpdateSessionTime()
	io.WriteString(s.wr, content)
}

func (s *ServiceSesion) isExpire() bool {
	s.rdLock.RLock()
	defer s.rdLock.RUnlock()
	return time.Now().Sub(s.SesionTickCount) > etc.S_LIFESPAN*time.Second
}

func (s *ServiceSesion) DelMsgKey() {
	key := s.Sid + "_smsg"
	redisclient.G_redisPool.Get().Do("DEL", key)
}

func (s *ServiceSesion) WriteMsg(content request.WebMsg) bool {
	defer s.UpdateSessionTime()
	select {
	case s.MsgPool <- content:
		//do nothing
	default:
		//warnning!
		log.Println("wite msg error!")
		return false
	}
	return true
	/*
		msgByte, err := json.Marshal(content)
		if err == nil {
			key := s.Sid + "_smsg"
			redisclient.G_redisPool.Get().Do("LPUSH", key, msgByte)
			//	redisclient.G_redisPool.Get().Do("EXPIRE", key, etc.S_MSG_LIFE_CYCLE)
		} else {
			log.Println(err.Error())
		}*/
}

func (s *ServiceSesion) GetMsg() (request.WebMsg, error) {
	defer s.UpdateSessionTime()
	var msg request.WebMsg
	select {
	case msg = <-s.MsgPool:
		//log.Println(msg.Msg)
		return msg, nil
	case <-time.After(time.Second * etc.S_QUERY_MSG_TIME):
		//log.Println("time out!!!")
		return msg, errors.New("time out")
	}
	/*
		key := s.Sid + "_smsg"
		msgArrayObj, err := redisclient.G_redisPool.Get().Do("BRPOP", key, etc.S_QUERY_MSG_TIME)
		//msgArrayObj, err := redisclient.G_redisPool.Get().Do("RPOP", key)
		if err == nil {
			msgObj, bConfirm := msgArrayObj.([]interface{})
			if bConfirm {
				msgByte, bIsBytes := msgObj[1].([]byte)
				if bIsBytes {
					jErr := json.Unmarshal(msgByte, &msg)
					return msg, jErr
				}
				return msg, errors.New("parse msg error")
			}
		}
		return msg, err
	*/
}

func (s *ServiceSesion) GetMsgLen() (int, bool) {
	nSize := len(s.MsgPool)
	return nSize, true
	/*
		key := s.Sid + "_smsg"
		msgArrayObj, err := redisclient.G_redisPool.Get().Do("LLEN", key)
		if err == nil {
			msgObj, bConfirm := msgArrayObj.(interface{})
			if bConfirm {
				msgLen, bIslen := msgObj.(int64)
				if bIslen {
					return int(msgLen), true
				}
				return 0, false
			}
		}
		return 0, false
	*/
}

func (s *ServiceSesion) UpdateSessionTime() {
	s.rdLock.Lock()
	s.SesionTickCount = time.Now()
	s.rdLock.Unlock()
}

//返回true表示发送过快
func (s *ServiceSesion) CheckSendTooMuch() bool {
	if time.Now().Sub(s.SesionTickCount) < etc.S_MIN_SEND_MSG_TIME*time.Second {
		return true
	}
	return false
}
